package io.xmu.dataanalysis.data.analysis;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import io.xmu.dataanalysis.data.BaseDataCache;
import io.xmu.dataanalysis.data.DataService;
import io.xmu.dataanalysis.data.OrderStatus;
import io.xmu.dataanalysis.entity.CateDailyData;
import io.xmu.dataanalysis.entity.Goods;
import io.xmu.dataanalysis.entity.Order;
import io.xmu.dataanalysis.entity.PV;
import io.xmu.dataanalysis.repository.CateDailyDataRepo;

/**
 * @author lepdou 2017-03-13
 */
@Component
public class CateDataAnalysis {

  @Autowired
  private DataService dataService;
  @Autowired
  private BaseDataCache dataCache;

  @Autowired
  private CateDailyDataRepo cateDailyDataRepo;

  @Transactional
  public void analysis(String partition) {
    cateDailyDataRepo.deleteByPartition(partition);

    analysisOrder(partition);
    analysisPV(partition);
  }

  private void analysisOrder(String partition) {
    Iterable<Order> orders = dataService.getOrderByPartition(partition);
    Multimap<Integer, Order> cateOrders = ArrayListMultimap.create();

    Map<Integer, Goods> orderMapGoods = Maps.newHashMap();
    for (Order order : orders) {
      Goods goods = dataCache.getGoods(order.getGoodsId());
      if (goods == null) {
        continue;
      }
      int shopId = goods.getShopId();
      int cateId = dataCache.getShop(shopId).getCateId();
      orderMapGoods.put(order.getId(), goods);
      cateOrders.put(cateId, order);
    }

    List<CateDailyData> cateDailyDatas = Lists.newLinkedList();

    Set<Integer> cateIds = cateOrders.keySet();
    for (Integer cateId : cateIds) {
      Collection<Order> cateDailyOrders = cateOrders.get(cateId);

      long sales = 0;
      int payedGoodsCount = 0;
      Set<Integer> payedUsers = Sets.newHashSet();

      for (Order order : cateDailyOrders) {
        //sales
        if (OrderStatus.isSuccessOrder(order.getStatus())) {
          sales += orderMapGoods.get(order.getId()).getPrice();
        }

        //payed goods count
        if (order.getStatus() == OrderStatus.PAY.value()) {
          payedGoodsCount++;
          payedUsers.add(order.getUserId());
        }
      }

      CateDailyData dailyData = new CateDailyData();

      dailyData.setCateId(cateId);
      dailyData.setPartition(partition);
      dailyData.setSales(sales);
      dailyData.setPayedGoodsCount(payedGoodsCount);
      dailyData.setPayedUserCount(payedUsers.size());

      cateDailyDatas.add(dailyData);
    }

    cateDailyDataRepo.save(cateDailyDatas);

  }

  private void analysisPV(String partition) {

    Iterable<PV> pvs = dataService.getPVByPartition(partition);

    Multimap<Integer, PV> cateIdMapPV = ArrayListMultimap.create();
    for (PV pv : pvs) {
      cateIdMapPV.put(dataCache.getShop(pv.getShopId()).getCateId(), pv);
    }

    List<CateDailyData> dailyDatas = Lists.newLinkedList();

    Set<Integer> cateIds = cateIdMapPV.keySet();
    for (Integer cateId : cateIds) {
      Collection<PV> catePVs = cateIdMapPV.get(cateId);

      int pvCounter = 0;
      Set<Integer> allUsers = Sets.newHashSet();

      for (PV pv : catePVs) {
        allUsers.add(pv.getUserId());
        pvCounter++;
      }

      CateDailyData dailyData = cateDailyDataRepo.findByCateIdAndPartition(cateId, partition);
      if (dailyData == null) {
        dailyData = new CateDailyData();
        dailyData.setCateId(cateId);
        dailyData.setPartition(partition);
      }

      dailyData.setPv(pvCounter);
      dailyData.setUv(allUsers.size());

      dailyDatas.add(dailyData);
    }

    cateDailyDataRepo.save(dailyDatas);
  }


}
